package com.thunder.reader.transaction;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.util.Log;

import com.thunder.reader.FeedSettings;
import com.thunder.reader.data.UrlReader;
import com.thunder.reader.parser.RssPullParser;
import com.thunder.reader.provider.Feed;
import com.thunder.reader.provider.FeedProvider;

public class UpdateFeedTransaction extends Transaction {
    private static final String TAG = "UpdateFeedTransaction";
    public static final String UPDATING_FEED_STARTED = "com.thunder.reader.UPDATING_FEED_STARTED";
    public static final String UPDATING_FEED_FINISHED = "com.thunder.reader.UPDATING_FEED_FINISHED";
    public static final String EXTRA_UPDATEING_FEED_ID = "updating_feed_id";
    private UpdateFeedWorker mWorker;
    
    public UpdateFeedTransaction(Context context, TransactionData data) {
        super(context, data);
    }

    @Override
    public void process() {
        mWorker = new UpdateFeedWorker();
        mWorker.start();
    }

    private class UpdateFeedWorker extends Thread {
        private ContentResolver mContentResolver;
        private Uri mUri;
        public UpdateFeedWorker() {
            mContentResolver = mContext.getContentResolver();
            mUri = mData.getUri();
        }
        
        @Override
        public void run() {
            try {
                Cursor cursor = null;
                final String[] projection = new String[] {
                        Feed.Source._ID,
                        Feed.Source.FEED_URL,
                };
                try {
                    switch (mData.getType()) {
                    case Transaction.TRANSACTION_TYPE_UPDATE_ALL:
                        cursor = mContentResolver.query(Feed.Source.CONTENT_URI, projection, null, null, null);
                        break;
                    case Transaction.TRANSACTION_TYPE_UPDATE_FEED:
                        cursor = mContentResolver.query(mUri, projection, null, null, null);
                        break;
                    case Transaction.TRANSACTION_TYPE_UPDATE_GROUP:
                        cursor = mContentResolver.query(Feed.Source.CONTENT_URI, 
                                projection, Feed.Source.GROUP_ID + "=?", new String[]{mUri.getPathSegments().get(1)}, null);
                        break;
                    default:
                        cursor = mContentResolver.query(Feed.Source.CONTENT_URI, projection, null, null, null);
                        break;
                    }
                    if (cursor == null) {
                        cursor = mContentResolver.query(mUri,
                                new String[] { Feed.Source.FEED_URL }, null,
                                null, null);
                    }
                    if (cursor != null && cursor.moveToFirst()) {
                        DatabaseUtils.dumpCursor(cursor);
                        do {
                            final int sourceId = cursor.getInt(0);
                            final Uri sourceUri = ContentUris.withAppendedId(Feed.Source.CONTENT_URI, sourceId);
                            notifyUpdatingStarted(sourceUri);
                            try {
                                InputStream is = new UrlReader(cursor.getString(1)).getInputStream();
                                RssPullParser parser = 
                                    new RssPullParser(mContentResolver, sourceUri, is);
                                parser.parse();
                                // TODO: after parsing, check for obsolete items
                                deleteObsoleteItems(mContentResolver, sourceId);
//                                dumpXml(cursor);
                            } catch (Exception e) {
                                Log.e(TAG, "Oops exception caught: ", e);
                            }
                            notifyUpdatingFinished(sourceUri);
                        } while (cursor.moveToNext());
                    }
                } finally {
                    if (cursor != null) {
                        cursor.close();
                    }
                    notifyObservers(mData);
                }
            } catch (Exception e) {
                Log.e(TAG, "bla, bla e", e);
            }
        }

        private void dumpXml(Cursor cursor) throws IOException {
            InputStream in = new UrlReader(cursor.getString(1)).getInputStream();
            String filename = cursor.getString(1);
            if (filename.endsWith("/")) {
                filename = filename.substring(0, filename.lastIndexOf("/"));
            }
            filename = filename.substring(
            	filename.lastIndexOf("/"),
            	filename.length());
            OutputStream out = new FileOutputStream(
            	"/sdcard/" + filename);
            byte[] buf = new byte[8912];
            int seg = 0;
            while ((seg = in.read(buf)) != -1) {
                out.write(buf, 0, seg);
            }
            in.close();
            out.close();
        }

        private void notifyUpdatingFinished(final Uri sourceUri) {
            final ContentValues values = new ContentValues(1);
            values.put(Feed.Source.UPDATING, 0);
            mContentResolver.update(sourceUri, values, null, null);
        }

        private void notifyUpdatingStarted(final Uri sourceUri) {
            final ContentValues values = new ContentValues(1);
            values.put(Feed.Source.UPDATING, 1);
            mContentResolver.update(sourceUri, values, null, null);
        }

        private void deleteObsoleteItems(ContentResolver cr, int sourceId) {
            final Cursor articles = cr.query(Feed.Article.CONTENT_URI, 
                    new String[]{Feed.Article._ID}, "source_id=?", 
                    new String[]{String.valueOf(sourceId)}, FeedProvider.ARTICLE_ORDER);
            if (!articles.moveToFirst()) {
                Log.e(TAG, "oops articles for sourceid " + sourceId + " is empty");
                return;
            }
            if (articles.getCount() < FeedSettings.getArticleLimit()) {
                Log.e(TAG, "oops there are only " + FeedSettings.getArticleLimit() + " items in " + sourceId);
                return;
            }
            if (!articles.moveToPosition(FeedSettings.getArticleLimit())) {
                Log.e(TAG, "cannot move to " + FeedSettings.getArticleLimit() + " items in " + sourceId);
                return;
            }
            do {
                cr.delete(Feed.Article.CONTENT_URI, "_id=?", new String[]{articles.getString(0)});
            } while (articles.moveToNext());
        }
    }

    @Override
    public void cancelProcess() {
    }
}